﻿using ApplicationModels.A03.Photographs;
using ApplicationModels.A08.Statistics;
using AutoMapper;
using Commons.Helpers;
using Commons.Responses;
using EntityModels.E03.Photographs;
using EntityModels.E06.Socializes;
using EntityModels.E08.Statistics;
using IApplicationServices;
using IRepositories;
using Newtonsoft.Json;
using StackExchange.Redis;
using System.Linq.Expressions;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace ApplicationService
{
    public class PhotographService:BaseApplicationService<Guid,Photograph, PhotographAM>, IPhotographService
    {
        private readonly RedisHelper redisHelper;
        private readonly IPhotographRepository _repository;
        public PhotographService(IPhotographRepository re, IMapper mapper) :base(re,mapper)
        {
            redisHelper = new RedisHelper();
            _repository = re;
        }

        public async Task<DatasResponse<PhotographAM>> GetPhotographsWithLikeStatusAsync(int pageIndex, int pageSize, Expression<Func<Photograph, bool>> predicate,Guid userId)
        {
            var photographs = await GetBySelectAsync(pageIndex, pageSize, predicate);
            foreach (var item in photographs.Datas)
            {
                item.IsLiked = await _repository.IsWorkLikedByUserAsync(item.Id, userId);
                item.IsStar = await _repository.IsWorkStarByUserAsync(item.Id, userId);
            }
            return photographs;
        }
        
        public async Task<DataResponse<PhotographAM>> GetPhotographWithLikeStatusAsync( Guid id, Guid userId)
        {
            var res = await base.GetByIdAsync(id);
            res.Data.IsLiked = await _repository.IsWorkLikedByUserAsync(id, userId);
            res.Data.IsStar = await _repository.IsWorkStarByUserAsync(id, userId);
            return res;
        }
        public async Task<DatasResponse<PhotographAM>> GetPhotographsWithLikeStatusByFollowAsync( Guid userId)
        {

            var bos = await _repository.GetPhotographsByFollow(userId);
            var photographs = Mapper.Map<List<PhotographAM>>(bos);
            var redisKey = "";
            var redisValue = "";
            foreach (var data in photographs)
            {
                redisKey = "statistics_photograph_" + data.Id;
                redisValue = redisHelper.StringGet(redisKey);
                data.IsLiked = await _repository.IsWorkLikedByUserAsync(data.Id, userId);
                data.IsStar = await _repository.IsWorkStarByUserAsync(data.Id, userId);
                if (redisValue == null)
                {
                    var sbo = (await Repository.GetOtherAsync<int, PhotographStatistics>(x => x.PhotographId == data.Id)).Data;
                    var sam = Mapper.Map<PhotographStatisticsAM>(sbo);
                    data.SetCount(sam.WatchCount, sam.LikeCount, sam.StarCount);
                    redisValue = JsonConvert.SerializeObject(sam);
                    redisHelper.StringSet(redisKey, redisValue);
                }
                else
                {
                    var sam = JsonConvert.DeserializeObject<PhotographStatisticsAM>(redisValue);
                    data.SetCount(sam.WatchCount, sam.LikeCount, sam.StarCount);
                }
            }
            return new DatasResponse<PhotographAM>(0, photographs);
        }
        public override async Task<DatasResponse<PhotographAM>> GetBySelectAsync(int pageIndex, int pageSize, Expression<Func<Photograph, bool>> predicate)
        {
            var redisKey = "";
            var redisValue = "";
            var res =  await base.GetBySelectAsync(pageIndex, pageSize, predicate);
            foreach (var data in res.Datas)
            {
                redisKey = "statistics_photograph_" + data.Id;
                redisValue = redisHelper.StringGet(redisKey);
                if (redisValue == null)
                {
                    var sbo = (await Repository.GetOtherAsync<int, PhotographStatistics>(x => x.PhotographId == data.Id)).Data;
                    var sam = Mapper.Map<PhotographStatisticsAM>(sbo);
                    data.SetCount(sam.WatchCount, sam.LikeCount, sam.StarCount);
                    redisValue = JsonConvert.SerializeObject(sam);
                    redisHelper.StringSet(redisKey, redisValue);
                }
                else
                {
                    var sam = JsonConvert.DeserializeObject<PhotographStatisticsAM>(redisValue);
                    data.SetCount(sam.WatchCount, sam.LikeCount, sam.StarCount);
                }
            }
            return res;
        }



        public override async Task<MessageResponse> AddAsync(PhotographAM apiBo)
        {
            var bo = Mapper.Map<Photograph>(apiBo);
            var res = await  Repository.AddAsync(bo);
            if (res.Successed)
            {
                bo = res.Data;
                var sbo = new PhotographStatistics(res.Data.Id);
                var otherRes = await Repository.AddOtherAsync<int, PhotographStatistics>(sbo);
                if (otherRes.Successed)
                {
                    var sam = Mapper.Map<PhotographStatisticsAM>(sbo);
                    var redisKey = "statistics_photograph_" + bo.Id;
                    var redisValue = JsonConvert.SerializeObject(sam);
                    redisHelper.StringSet(redisKey, redisValue);
                    return new MessageResponse("添加成功!");
                }
            }
            return new MessageResponse("添加失败!", false);
        }

        public async Task AddHistory(string photographId)
        {
            var redisKey = "statistics_photograph_" + photographId;
            var redisValue = await redisHelper.StringGetAsync(redisKey);
            var sam = JsonConvert.DeserializeObject<PhotographStatisticsAM>(redisValue);
            sam.WatchCount += 1;
            redisValue = JsonConvert.SerializeObject(sam);
            await redisHelper.StringSetAsync(redisKey,redisValue);
            var sbo = Mapper.Map<PhotographStatistics>(sam);
            await Repository.UpdateOtherAsync<int, PhotographStatistics>(sbo);
        }



    }
}
